Skip to content

Conversation

ludvigz
Copy link
Member

@ludvigz ludvigz commented Nov 13, 2026

Purpose

The publishBuild mutation is public, with no authentication, rate limiting or quotas, so anyone could flood the database with spam. This PR adds server-side abuse protection while keeping publishing anonymous, and adds limits on GraphQL request cost.

Changes

  • Rate limit publishBuild per client IP: 5 attempts per 10 minutes, using rate-limiter-flexible. The check runs first in the resolver, so blocked requests create no database entries. Exceeding it returns HTTP 429 with a Retry-After header and error code RATE_LIMITED. Every attempt counts, including invalid ones and each alias in a single request.
  • Add a GraphQL validation rule (limits.ts) that rejects operations nested deeper than 8 levels or selecting more than 100 fields (HTTP 400). Fragments are expanded when counting; introspection is not counted.
  • Limit request bodies to 100 KB (HTTP 413 with a JSON error).
  • Pass the client IP to resolvers through the GraphQL context, and add a TRUST_PROXY setting so the real visitor IP is used behind Apache.
  • All limits are constants in backend/server/src/config.ts. Only TRUST_PROXY is read from .env.
  • Document the limits in the README ("Abuse protection and request limits") and TRUST_PROXY in .env.example.
  • Add tests for the new limits in backend/server/src/test/.
  • Update resolvers.test.ts to mock config.js, because resolvers.ts now imports the rate limiter, which loads the real config.

Deployment note: set TRUST_PROXY=1 in the VM's backend/server/.env, and make sure port 3001 is not reachable from outside the VM. Without TRUST_PROXY, all visitors share the proxy's address and one limit. The rate limit counters are kept in memory and reset when the backend restarts.

Related issues

Closes #89

Verification

Automated checks, run from backend/server:

  • npm test: all 20 tests pass, including 10 new ones. They cover the depth and field limits (including fragments, fragment cycles and introspection) and the publish limit (normal publishing works, excess attempts are blocked with no database queries, each IP is limited separately, invalid attempts count).

Manually tested 6 publish build attempts. 5 were successfull, the 6th showed an error (see screenshot)

Screenshots

image

Checklist

  • I have reviewed my own changes.
  • The changes meet the linked issue's acceptance criteria, where applicable.
  • I have verified the changes and recorded the results above.
  • I have added or updated tests where needed.
  • I have updated documentation where needed.
  • I have included screenshots for visual changes, or marked them not applicable.

@ludvigz ludvigz self-assigned this Nov 13, 2026
@ludvigz ludvigz requested a review from a team as a code owner November 13, 2026 17:30
@ludvigz ludvigz linked an issue Nov 13, 2026 that may be closed by this pull request
5 tasks
Copy link
Member

@oscarog oscarog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@oscarog oscarog merged commit 321a746 into dev Nov 13, 2026
@oscarog oscarog deleted the 89-add-abuse-protection-for-anonymous-build-publishing branch November 13, 2026 22:09
Sign in to join this conversation on GitHub.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add abuse protection for anonymous build publishing
2 participants